﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Mail;
using Moq;
using NUnit.Framework;
using StructureMap;

namespace IndyCodeCamp
{
    class Program
    {
        static void Main( string[] args )
        {
            ObjectFactory.Initialize(x =>
             {
                 x.ForRequestedType<IRecipientProvider>().TheDefault.Is.OfConcreteType
                     <CsvRecipientProvider>().WithCtorArg("filename").EqualTo(
                     @"c:\people.csv");

                 x.ForRequestedType<IMailService>().TheDefault.Is.OfConcreteType
                     <SmtpMailService>().
                     WithCtorArg("host").EqualTo("indycodecamp.com").
                     WithCtorArg("port").EqualTo(123);
             }
                );

            var mailMerge = ObjectFactory.GetInstance<MailMerge>();
            mailMerge.Go("me@indycodecamp.com", "You have inherited!",
                "Dear {0} {1} you have inherited 23 million dollars... all you have to do is let me swindle you first.");
        }
    }

    public interface IRecipientProvider
    {
         IEnumerable<Person> GetRecipients();
    }

    public interface IMailService
    {
        void Send(string from, string to, string subject, string body);
    }

    public class SmtpMailService : IMailService
    {
        private SmtpClient _smtpClient;

        public SmtpMailService(string host, int port)
        {
            _smtpClient = new SmtpClient(host, port);
        }
        public void Send(string from, string to, string subject, string body)
        {
            _smtpClient.Send(from, to, subject, body);
        }
    }

    [TestFixture]
    public class MailMergeTests
    {
        [Test]
        public void ShouldCallSendOnMailerForEachRecipient()
        {
            var recipMock = new Mock<IRecipientProvider>();
            var mailerMock = new Mock<IMailService>();

            recipMock.Setup(r => r.GetRecipients()).Returns(new List<Person>()
                                                                {
                                                                    new Person()
                                                                        {
                                                                            FirstName = "Jon",
                                                                            LastName = "Fuller",
                                                                            EmailAddress = "nospam@indycodecamp.com"
                                                                        }
                                                                });

            new MailMerge(recipMock.Object, mailerMock.Object).Go("me", "subject", "message");

            mailerMock.Verify(m => m.Send(
                It.IsAny<string>(),
                It.IsAny<string>(),
                It.IsAny<string>(),
                It.IsAny<string>()
                ),
            Times.Exactly(2));
        }
    }

    public class MailMerge
    {
        private IMailService _mailer;
        private IRecipientProvider _recipientProvider;

        public MailMerge(IRecipientProvider recipientProvider, IMailService mailer)
        {
            _recipientProvider = recipientProvider;
            _mailer = mailer;
        }

        public void Go(string from, string subject, string message)
        {
            foreach (var person in _recipientProvider.GetRecipients())
                _mailer.Send(from,
                    person.EmailAddress,
                    subject,
                    string.Format(message, person.FirstName, person.LastName));
        }
    }

    public class RecipientProvider : IRecipientProvider
    {
        public IEnumerable<Person> GetRecipients()
        {
            return new List<Person>() {new Person()
                                           {
                                               FirstName = "Jon",
                                               LastName = "Fuller",
                                               EmailAddress = "you@indycodecamp.com"
                                           }};
        }
    }

    public class CsvRecipientProvider : IRecipientProvider
    {
        private string _filename;

        public CsvRecipientProvider(string filename)
        {
            _filename = filename;
        }
        public IEnumerable<Person> GetRecipients()
        {
            using (var reader = new StreamReader(_filename))
            {
                // read lines, create persons
                return new List<Person>();
            }
        }
    }

    public class Person
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string EmailAddress { get; set;}
    }
}
